home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-04
/
ms_sh21s.zip
/
SH210
/
SRC
/
SH10.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-14
|
35KB
|
1,674 lines
/* MS-DOS SHELL - Function Processing
*
* MS-DOS SHELL - Copyright (c) 1990,1,2 Data Logic Limited
*
* This code is subject to the following copyright restrictions:
*
* 1. Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice is duplicated in the
* source form and the copyright notice in file sh6.c is displayed
* on entry to the program.
*
* 2. The sources (or parts thereof) or objects generated from the sources
* (or parts of sources) cannot be sold under any circumstances.
*
* Note: The PrintProcessTree code is based on code written by Kai Uwe Rommel
*
* $Header: /usr/users/istewart/src/shell/sh2.1/RCS/sh10.c,v 2.4 1992/12/14 10:54:56 istewart Exp $
*
* $Log: sh10.c,v $
* Revision 2.4 1992/12/14 10:54:56 istewart
* BETA 215 Fixes and 2.1 Release
*
* Revision 2.3 1992/11/06 10:03:44 istewart
* 214 Beta test updates
*
* Revision 2.2 1992/07/16 14:33:34 istewart
* Beta 212 Baseline
*
* Revision 2.1 1992/07/10 10:52:48 istewart
* 211 Beta updates
*
* Revision 2.0 1992/04/13 17:39:09 Ian_Stewartson
* MS-Shell 2.0 Baseline release
*
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <setjmp.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>
#include <dirent.h>
#ifdef OS2
#define INCL_DOSSESMGR
#define INCL_DOSPROCESS
#define INCL_DOSMODULEMGR
#include <os2.h>
#else
#include <dos.h>
#endif
#include "sh.h"
/* Function declarations */
static void near PrintCommand (C_Op *);
static void near PrintIOInformation (IO_Actions *);
static void near PrintCaseCommand (C_Op *);
static void near PrintIndentedString (char *, int);
static void near SaveReleaseExecuteTree (C_Op *, void (*)(void *));
static void near SaveReleaseCommand (C_Op *, void (*)(void *));
static void near SaveReleaseCaseCommand (C_Op *, void (*)(void *));
static C_Op * near CopyExecuteTree (C_Op *);
static void near CopyCommand (C_Op *, C_Op *);
static C_Op * near CopyCaseCommand (C_Op *);
static void SaveTreeEntry (void *);
static void * near DuplicateField (void *, size_t);
static int FindFunction (void *, void *);
static int FindAlias (void *, void *);
static int SearchFunction (void *, void *);
static int SearchAlias (void *, void *);
static void UntrackAlias (void *, VISIT, int);
static void DisplayFunction (void *, VISIT, int);
static void DisplayAlias (void *, VISIT, int);
#ifdef OS2
static void DisplayJob (void *, VISIT, int);
static void CountJob (void *, VISIT, int);
static int SearchJob (void *, void *);
static int FindJob (void *, void *);
static void FindJobByString (void *, VISIT, int);
static int FindJobByPID (void *, void *);
extern USHORT APIENTRY DosQProcStatus(PVOID pBuf, USHORT cbBuf);
#endif
#ifdef OS2
static char *JobSearchKey; /* Job search string */
static int NumberOfJobs = 0; /* Number of Jobs */
static JobList **JobSearchEntry; /* Matching entry */
#endif
static bool DisplayListMode = FALSE;/* Mode for Display Job/Alias */
static int Print_indent; /* Current indent level */
static char *LIT_done = "done\n";
/*
* Print ALL functions
*/
int PrintAllFunctions (void)
{
twalk (FunctionTree, DisplayFunction);
return 0;
}
/*
* TWALK function to display the JOB, FUNCTION and ALIAS trees
*/
#ifdef OS2
static void CountJob (void *key, VISIT visit, int level)
{
if ((visit == postorder) || (visit == leaf))
NumberOfJobs++;
}
static void DisplayJob (void *key, VISIT visit, int level)
{
if ((visit == postorder) || (visit == leaf))
{
printf ("[%d] %c", (*(JobList **)key)->Number,
((*(JobList **)key)->Number == CurrentJob)
? '+'
: (((*(JobList **)key)->Number == PreviousJob)
? '-' : ' '));
if (DisplayListMode)
printf (" %d", (*(JobList **)key)->pid);
putchar (CHAR_TAB);
fflush (stdout);
DisplayLineWithControl ((*(JobList **)key)->Command);
}
}
#endif
static void DisplayFunction (void *key, VISIT visit, int level)
{
if ((visit == postorder) || (visit == leaf))
PrintFunction ((*(FunctionList **)key)->tree);
}
static void DisplayAlias (void *key, VISIT visit, int level)
{
if (((visit == postorder) || (visit == leaf)) &&
(!DisplayListMode || (*(AliasList **)key)->Tracked))
PrintAlias ((*(AliasList **)key)->name);
}
/*
* print the execute tree - used for displaying functions
*/
void PrintFunction (register C_Op *t)
{
char **wp;
if (t == (C_Op *)NULL)
return;
/* Check for start of print */
if (t->type == TFUNC)
{
Print_indent = 0;
printf (LIT_2Strings, t->str, "()");
PrintFunction (t->left);
fflush (stdout);
return;
}
/* Otherwise, process the tree and print it */
switch (t->type)
{
case TPAREN: /* () */
case TCOM: /* A command process */
PrintCommand (t);
return;
case TPIPE: /* Pipe processing */
PrintFunction (t->left);
PrintIndentedString ("|\n", 0);
PrintFunction (t->right);
return;
case TLIST: /* Entries in a for statement */
PrintFunction (t->left);
PrintFunction (t->right);
return;
case TOR: /* || and && */
case TAND:
PrintFunction (t->left);
if (t->right != (C_Op *)NULL)
{
PrintIndentedString ((t->type == TAND) ? "&&\n" : "||\n", 0);
PrintFunction (t->right);
}
return;
case TFOR: /* First part of a for statement*/
case TSELECT:
PrintIndentedString ((t->type == TFOR) ? "for " : "select ", 0);
fputs (t->str, stdout);
if ((wp = t->words) != (char **)NULL)
{
fputs (" in", stdout);
while (*wp != (char *)NULL)
printf (" %s", *wp++);
}
putchar (CHAR_NEW_LINE);
PrintIndentedString ("do\n", 1);
PrintFunction (t->left);
PrintIndentedString (LIT_done, -1);
return;
case TWHILE: /* WHILE and UNTIL functions */
case TUNTIL:
PrintIndentedString ((t->type == TWHILE) ? "while " : "until ", 1);
PrintFunction (t->left);
PrintIndentedString ("do\n", 0);
PrintFunction (t->right);
PrintIndentedString (LIT_done, -1);
return;
case TIF: /* IF and ELSE IF functions */
case TELIF:
if (t->type == TIF)
PrintIndentedString ("if\n", 1);
else
PrintIndentedString ("elif\n", 1);
PrintFunction (t->left);
if (t->right != (C_Op *)NULL)
{
Print_indent -= 1;
PrintIndentedString ("then\n", 1);
PrintFunction (t->right->left);
if (t->right->right != (C_Op *)NULL)
{
Print_indent -= 1;
if (t->right->right->type != TELIF)
PrintIndentedString ("else\n", 1);
PrintFunction (t->right->right);
}
}
if (t->type == TIF)
PrintIndentedString ("fi\n", -1);
return;
case TCASE: /* CASE function */
PrintIndentedString ("case ", 1);
printf (LIT_2Strings, t->str, "in");
PrintCaseCommand (t->left);
PrintIndentedString (" esac\n", -1);
return;
case TBRACE: /* {} statement */
PrintIndentedString ("{\n", 1);
if (t->left != (C_Op *)NULL)
PrintFunction (t->left);
PrintIndentedString ("}\n", -1);
return;
}
}
/*
* Print a command line
*/
static void near PrintCommand (register C_Op *t)
{
IO_Actions **iopp;
char **owp = t->words;
/* Parenthesis ? */
if (t->type == TPAREN)
{
PrintIndentedString ("(\n", 1);
PrintFunction (t->left);
PrintIndentedString (")", -1);
}
else
{
PrintIndentedString (null, 0);
while (*owp != (char *)NULL)
{
fputs (*owp++, stdout);
if (*owp != (char *)NULL)
putchar (CHAR_SPACE);
}
}
/* Set up anyother IO required */
if ((iopp = t->ioact) != (IO_Actions **)NULL)
{
while (*iopp != (IO_Actions *)NULL)
PrintIOInformation (*iopp++);
}
putchar (CHAR_NEW_LINE);
}
/*
* Print the IO re-direction
*/
static void near PrintIOInformation (register IO_Actions *iop)
{
int unit = iop->io_unit;
char *type;
if (unit == IODEFAULT) /* take default */
unit = (iop->io_flag & (IOREAD | IOHERE)) ? STDIN_FILENO
: STDOUT_FILENO;
/* Output unit number */
switch (iop->io_flag)
{
case IOHERE:
case IOHERE | IOXHERE:
type = "<<";
break;
case IOREAD:
type = "<";
break;
case IOWRITE | IOCAT:
type = ">>";
break;
case IOWRITE:
type = ">";
break;
case IODUP:
printf ("%d>&%c", unit, *iop->io_name);
return;
}
printf ("%d%s%s", unit, type, iop->io_name);
}
/*
* Print out the contents of a case statement
*/
static void near PrintCaseCommand (C_Op *t)
{
register C_Op *t1;
register char **wp;
if (t == (C_Op *)NULL)
return;
/* type - TLIST - go down the left tree first and then processes this level */
if (t->type == TLIST)
{
PrintCaseCommand (t->left);
t1 = t->right;
}
else
t1 = t;
/* Output the conditions */
PrintIndentedString (null, 0);
for (wp = t1->words; *wp != (char *)NULL;)
{
printf ("%s%s", *wp, *(wp + 1) != (char *)NULL ? " | " : null);
++wp;
}
puts (" )");
Print_indent += 1;
/* Output the commands */
PrintFunction (t1->left);
PrintIndentedString (";;\n", -1);
}
/*
* Print an indented string
*/
static void near PrintIndentedString (char *cp, int indent)
{
int i;
if (indent < 0)
Print_indent += indent;
for (i = 0; i < (Print_indent / 2); i++)
putchar ('\t');
if (Print_indent % 2)
fputs (" ", stdout);
fputs (cp, stdout);
if (indent > 0)
Print_indent += indent;
}
/*
* TWALK and TDELETE compare functions for FUNCTION, ALIAS and JOB trees
*
* Note: We know about these two function, so we know the key is always
* the first parameter. So we only pass the char * not the FunctionList
* pointer (in the case of JOB, its an int *)
*/
static int FindFunction (void *key1, void *key2)
{
return strcmp (key1, ((FunctionList *)key2)->tree->str);
}
static int FindAlias (void *key1, void *key2)
{
return strcmp (key1, ((AliasList *)key2)->name);
}
#ifdef OS2
/* By string name */
static void FindJobByString (void *key, VISIT visit, int level)
{
if (JobSearchEntry != (JobList **)NULL)
return;
if (((visit == postorder) || (visit == leaf)) &&
((*JobSearchKey == '?') &&
(strstr (((JobList *)key)->Command, JobSearchKey) != (char *)NULL)) ||
((*JobSearchKey != '?') &&
(strncmp (JobSearchKey, ((JobList *)key)->Command,
strlen (JobSearchKey)) == 0)))
JobSearchEntry = &key;
}
/* By process id */
static int FindJobByPID (void *key1, void *key2)
{
return *(PID *)key1 - ((JobList *)key2)->pid;
}
/* By job number */
static int FindJob (void *key1, void *key2)
{
return *(int *)key1 - ((JobList *)key2)->Number;
}
#endif
/*
* Look up a function in the save tree
*/
FunctionList *LookUpFunction (char *name)
{
FunctionList **fp = (FunctionList **)tfind (name, &FunctionTree,
FindFunction);
return fp != (FunctionList **)NULL ? *fp : (FunctionList *)NULL;
}
/*
* Delete a function tree
*/
void DeleteFunction (C_Op *t)
{
char *name = t->str;
register FunctionList *fp = LookUpFunction (name);
void (*save_signal)(int);
if (fp == (FunctionList *)NULL)
return;
/* Disable signals */
save_signal = signal (SIGINT, SIG_IGN);
/* Free the tree and delete the entry */
tdelete (name, &FunctionTree, FindFunction);
SaveReleaseExecuteTree (fp->tree, ReleaseMemoryCell);
ReleaseMemoryCell ((void *)fp);
/* Restore signals */
signal (SIGINT, save_signal);
}
/*
* TSEARCH compare functions for FUNCTION, ALIAS and JOB trees
*/
static int SearchFunction (void *key1, void *key2)
{
return strcmp (((FunctionList *)key1)->tree->str,
((FunctionList *)key2)->tree->str);
}
static int SearchAlias (void *key1, void *key2)
{
return strcmp (((AliasList *)key1)->name, ((AliasList *)key2)->name);
}
#ifdef OS2
static int SearchJob (void *key1, void *key2)
{
return ((JobList *)key1)->Number - ((JobList *)key2)->Number;
}
#endif
/*
* Save a function tree
*/
bool SaveFunction (C_Op *t)
{
char *name = t->str;
register FunctionList *fp;
void (*save_signal)(int);
if (!IsValidAliasName (name, FALSE))
{
PrintWarningMessage (BasicErrorMessage, name, "Invalid function name");
return FALSE;
}
/* Create new entry */
if ((fp = (FunctionList *)GetAllocatedSpace (sizeof (FunctionList)))
== (FunctionList *)NULL)
return FALSE;
/* Delete the old function if it exists */
DeleteFunction (t);
/* Disable signals */
save_signal = signal (SIGINT, SIG_IGN);
fp->tree = t;
fp->Traced = FALSE;
/* Set up the tree */
if (tsearch (fp, &FunctionTree, SearchFunction) != (void *)NULL)
{
SetMemoryAreaNumber ((void *)fp, 0);
SaveReleaseExecuteTree (t, SaveTreeEntry);
}
/* Restore signals */
signal (SIGINT, save_signal);
return TRUE;
}
/*
* Set ExTree areas to zero function
*/
static void SaveTreeEntry (void *s)
{
SetMemoryAreaNumber (s, 0);
}
/*
* Set/Free function tree area by recursively processing of tree
*/
static void near SaveReleaseExecuteTree (C_Op *t, void (* func)(void *))
{
char **wp;
if (t == (C_Op *)NULL)
return;
/* Check for start of print */
if (t->type == TFUNC)
{
(*func)((void *)t->str);
SaveReleaseExecuteTree (t->left, func);
}
/* Otherwise, process the tree and print it */
switch (t->type)
{
case TPAREN: /* () */
case TCOM: /* A command process */
SaveReleaseCommand (t, func);
break;
case TPIPE: /* Pipe processing */
case TLIST: /* Entries in a for statement */
case TOR: /* || and && */
case TAND:
case TWHILE: /* WHILE and UNTIL functions */
case TUNTIL:
SaveReleaseExecuteTree (t->left, func);
SaveReleaseExecuteTree (t->right, func);
break;
case TFOR: /* First part of a for statement*/
case TSELECT:
(*func)((void *)t->str);
if ((wp = t->words) != (char **)NULL)
{
while (*wp != (char *)NULL)
(*func) ((void *)*wp++);
(*func)((void *)t->words);
}
SaveReleaseExecuteTree (t->left, func);
break;
case TIF: /* IF and ELSE IF functions */
case TELIF:
if (t->right != (C_Op *)NULL)
{
SaveReleaseExecuteTree (t->right->left, func);
SaveReleaseExecuteTree (t->right->right, func);
(*func)((void *)t->right);
}
case TBRACE: /* {} statement */
SaveReleaseExecuteTree (t->left, func);
break;
case TCASE: /* CASE function */
(*func)((void *)t->str);
SaveReleaseCaseCommand (t->left, func);
break;
}
(*func)((void *)t);
}
/*
* Set/Free a command line
*/
static void near SaveReleaseCommand (C_Op *t, void (* func)(void *))
{
IO_Actions **iopp;
char **wp = t->words;
/* Parenthesis ? */
if (t->type == TPAREN)
SaveReleaseExecuteTree (t->left, func);
else
{
while (*wp != (char *)NULL)
(*func)((void *)*wp++);
(*func) ((void *)t->words);
}
/* Process up any IO required */
if ((iopp = t->ioact) != (IO_Actions **)NULL)
{
while (*iopp != (IO_Actions *)NULL)
{
(*func)((void *)(*iopp)->io_name);
(*func)((void *)*iopp);
iopp++;
}
(*func)((void *)t->ioact);
}
}
/*
* Set/Free the contents of a case statement
*/
static void near SaveReleaseCaseCommand (C_Op *t, void (* func)(void *))
{
register C_Op *t1;
register char **wp;
if (t == (C_Op *)NULL)
return;
/* type - TLIST - go down the left tree first and then processes this level */
if (t->type == TLIST)
{
SaveReleaseCaseCommand (t->left, func);
(*func)((void *)t->left);
t1 = t->right;
}
else
t1 = t;
/* Set/Free the conditions */
for (wp = t1->words; *wp != (char *)NULL;)
(*func)((void *)*(wp++));
(*func)((void *)t1->words);
SaveReleaseExecuteTree (t1->left, func);
if (t1 == t->right)
(*func)((void *)t->right);
(*func)((void *)t);
}
/*
* Copy function tree area by recursively processing of tree
*/
static C_Op * near CopyExecuteTree (C_Op *Old_t)
{
char **wp;
C_Op *New_t;
Word_B *wb = (Word_B *)NULL;
if (Old_t == (C_Op *)NULL)
return (C_Op *)NULL;
New_t = (C_Op *) DuplicateField (Old_t, sizeof (C_Op));
/* Check for start of print */
if (Old_t->type == TFUNC)
{
New_t->str = StringCopy (Old_t->str);
New_t->left = CopyExecuteTree (Old_t->left);
}
/* Otherwise, process the tree and print it */
switch (Old_t->type)
{
case TPAREN: /* () */
case TCOM: /* A command process */
CopyCommand (Old_t, New_t);
break;
case TPIPE: /* Pipe processing */
case TLIST: /* Entries in a for statement */
case TOR: /* || and && */
case TAND:
case TWHILE: /* WHILE and UNTIL functions */
case TUNTIL:
New_t->left = CopyExecuteTree (Old_t->left);
New_t->right = CopyExecuteTree (Old_t->right);
break;
case TFOR: /* First part of a for statement*/
case TSELECT:
New_t->str = StringCopy (Old_t->str);
if ((wp = Old_t->words) != (char **)NULL)
{
while (*wp != (char *)NULL)
wb = AddWordToBlock (StringCopy (*(wp++)), wb);
New_t->words = GetWordList (AddWordToBlock (NOWORD, wb));
}
New_t->left = CopyExecuteTree (Old_t->left);
break;
case TIF: /* IF and ELSE IF functions */
case TELIF:
if (Old_t->right != (C_Op *)NULL)
{
New_t->right = (C_Op *)DuplicateField (Old_t->right,
sizeof (C_Op));
New_t->right->left = CopyExecuteTree (Old_t->right->left);
New_t->right->right = CopyExecuteTree (Old_t->right->right);
}
case TBRACE: /* {} statement */
New_t->left = CopyExecuteTree (Old_t->left);
break;
case TCASE: /* CASE function */
New_t->str = StringCopy (Old_t->str);
New_t->left = CopyCaseCommand (Old_t->left);
break;
}
return New_t;
}
/*
* Copy a command line
*/
static void near CopyCommand (C_Op *Old_t, C_Op *New_t)
{
IO_Actions **iopp;
char **wp = Old_t->words;
Word_B *wb = (Word_B *)NULL;
IO_Actions *iop;
/* Parenthesis ? */
if (Old_t->type == TPAREN)
New_t->left = CopyExecuteTree (Old_t->left);
else
{
while (*wp != (char *)NULL)
wb = AddWordToBlock (StringCopy (*(wp++)), wb);
New_t->words = GetWordList (AddWordToBlock (NOWORD, wb));
}
/* Process up any IO required */
if ((iopp = Old_t->ioact) != (IO_Actions **)NULL)
{
wb = (Word_B *)NULL;
while (*iopp != (IO_Actions *)NULL)
{
iop = (IO_Actions *)DuplicateField (*iopp, sizeof (IO_Actions));
iop->io_name = StringCopy ((*iopp)->io_name);
wb = AddWordToBlock ((char *)iop, wb);
++iopp;
}
New_t->ioact = (IO_Actions **)GetWordList (AddWordToBlock (NOWORD, wb));
}
}
/*
* Copy the contents of a case statement
*/
static C_Op * near CopyCaseCommand (C_Op *Old_t)
{
register C_Op *Old_t1, *New_t, *New_t1;
register char **wp;
Word_B *wb = (Word_B *)NULL;
if (Old_t == (C_Op *)NULL)
return (C_Op *)NULL;
/* type - TLIST - go down the left tree first and then processes this level */
New_t = (C_Op *)DuplicateField (Old_t, sizeof (C_Op));
if (Old_t->type == TLIST)
{
New_t->left = CopyCaseCommand (Old_t->left);
New_t->right = (C_Op *)DuplicateField (Old_t->right, sizeof (C_Op));
Old_t1 = Old_t->right;
New_t1 = New_t->right;
}
else
{
New_t1 = New_t;
Old_t1 = Old_t;
}
/* Duplicate the word block */
wp = Old_t1->words;
while (*wp != (char *)NULL)
wb = AddWordToBlock (StringCopy (*(wp++)), wb);
New_t1->words = GetWordList (AddWordToBlock (NOWORD, wb));
New_t1->left = CopyExecuteTree (Old_t1->left);
return New_t;
}
/*
* Duplicate a field
*/
static void * near DuplicateField (void *source, size_t size)
{
return memcpy (GetAllocatedSpace (size), source, size);
}
/* Duplicate the tree */
C_Op *CopyFunction (C_Op *Old_t)
{
int *save_ErrorReturnPoint;
jmp_buf new_ErrorReturnPoint;
C_Op *New_t = (C_Op *)NULL;
/* Set up for error handling - like out of space */
save_ErrorReturnPoint = e.ErrorReturnPoint;
if (setjmp (new_ErrorReturnPoint) == 0)
New_t = CopyExecuteTree (Old_t);
e.ErrorReturnPoint = save_ErrorReturnPoint;
return New_t;
}
/*
* Alias processing
*/
void PrintAlias (char *name)
{
register AliasList *al = LookUpAlias (name, FALSE);
if ((al == (AliasList *)NULL) || (al->value == null))
return;
printf (ListVarFormat, name, al->value);
}
/*
* Print All Aliases
*/
int PrintAllAlias (bool tracked)
{
DisplayListMode = tracked; /* Set mode */
twalk (AliasTree, DisplayAlias);
return 0;
}
/*
* Save an alias
*/
bool SaveAlias (char *name, char *arguments, bool tracked)
{
register AliasList *al;
void (*save_signal)(int);
/* Create new entry */
if (((al = (AliasList *)GetAllocatedSpace (sizeof (AliasList)))
== (AliasList *)NULL) ||
((al->name = GetAllocatedSpace (strlen (name) + 1)) == (char *)NULL))
return FALSE;
if ((arguments != null) &&
((al->value = GetAllocatedSpace (strlen (arguments) + 1))
== (char *)NULL))
return FALSE;
/* Delete old name */
DeleteAlias (name);
/* Disable signals */
save_signal = signal (SIGINT, SIG_IGN);
strcpy (al->name, name);
/* Add it to the tree */
if (tsearch (al, &AliasTree, SearchAlias) != (void *)NULL)
{
SetMemoryAreaNumber ((void *)al, 0);
SetMemoryAreaNumber ((void *)al->name, 0);
if (arguments != null)
SetMemoryAreaNumber ((void *)strcpy (al->value, arguments), 0);
else
al->value = null;
al->Tracked = tracked;
}
/* Restore signals */
signal (SIGINT, save_signal);
return TRUE;
}
/*
* Delete an alias
*/
void DeleteAlias (char *name)
{
register AliasList **alp = (AliasList **)tfind (name, &AliasTree,
FindAlias);
void (*save_signal)(int);
register AliasList *al;
if (alp == (AliasList **)NULL)
return;
/* Disable signals */
save_signal = signal (SIGINT, SIG_IGN);
/* Delete the tree entry and release the memory */
al = *alp;
tdelete (name, &AliasTree, FindAlias);
ReleaseMemoryCell ((void *)al->name);
if (al->value != null)
ReleaseMemoryCell ((void *)al->value);
ReleaseMemoryCell ((void *)al);
/* Restore signals */
signal (SIGINT, save_signal);
}
/*
* Search for an Alias
*/
AliasList *LookUpAlias (char *name, bool CreateTracked)
{
AliasList **alp = (AliasList **)tfind (name, &AliasTree, FindAlias);
char *path;
/* If we found a tracked alias, which has been untracked, re-track it if
* necesary
*/
if ((alp != (AliasList **)NULL) && ((*alp)->value == null))
{
if (CreateTracked &&
((path = AllocateMemoryCell (FFNAME_MAX + 4)) != (char *)NULL) &&
(FindLocationOfExecutable (path, name) == EXTENSION_NOT_FOUND))
{
SetMemoryAreaNumber ((void *)path, 0);
(*alp)->value = path;
return *alp;
}
else
return (AliasList *)NULL;
}
return (alp == (AliasList **)NULL) ? (AliasList *)NULL : *alp;
}
/*
* Check for valid alias name
*/
bool IsValidAliasName (char *s, bool alias)
{
if (!isalpha (*s) || LookUpSymbol (s))
return FALSE;
while (isalnum (*s))
++s;
return (*s) ? FALSE : TRUE;
}
/*
* Untrack all Aliases
*/
void UnTrackAllAliases (void)
{
twalk (AliasTree, UntrackAlias);
}
/*
* The associate TWALK function
*/
static void UntrackAlias (void *key, VISIT visit, int level)
{
AliasList *al = *(AliasList **)key;
if (((visit == postorder) || (visit == leaf)) && al->Tracked &&
(al->value != null))
{
ReleaseMemoryCell ((void *)al->value);
al->value = null;
}
}
#ifdef OS2
/*
* Look up a job in the save tree
*/
JobList *LookUpJob (int JobNumber)
{
JobList **jp = (JobList **)tfind (&JobNumber, &JobTree, FindJob);
return jp != (JobList **)NULL ? *jp : (JobList *)NULL;
}
/*
* Search for a job
*/
JobList *SearchForJob (char *String)
{
JobSearchKey = String;
JobSearchEntry = (JobList **)NULL;
if ((strcmp (String, "%") == 0) || (strcmp (String, "+") == 0))
return LookUpJob (CurrentJob);
else if (strcmp (String, "-") == 0)
return LookUpJob (PreviousJob);
/* Search for it */
twalk (JobTree, FindJobByString);
return JobSearchEntry != (JobList **)NULL ? *JobSearchEntry
: (JobList *)NULL;
}
/*
* Delete a job tree
*/
void DeleteJob (PID pid)
{
register JobList **jpp = (JobList **)tfind (&pid, &JobTree,
FindJobByPID);
void (*save_signal)(int);
JobList *jp;
if (jpp == (JobList **)NULL)
return;
/* Disable signals */
save_signal = signal (SIGINT, SIG_IGN);
jp = *jpp;
/* Free the tree and delete the entry */
tdelete (&pid, &JobTree, FindJobByPID);
if (jp->Number == PreviousJob)
PreviousJob = 0;
if (jp->Number == CurrentJob)
CurrentJob = PreviousJob;
ReleaseMemoryCell ((void *)jp->Command);
ReleaseMemoryCell ((void *)jp);
/* Restore signals */
signal (SIGINT, save_signal);
}
/*
* Save a job ID
*/
int AddNewJob (PID pid, char *command)
{
register JobList *jp;
static int JobNumber = 1;
void (*save_signal)(int);
char *tmp;
/* We if we can get the full command */
if ((tmp = GetLastHistoryString ()) != (char *)NULL)
command = tmp;
/* Create new entry */
if (((jp = (JobList *)GetAllocatedSpace (sizeof (JobList))) == (JobList *)NULL) ||
((jp->Command = GetAllocatedSpace (strlen (command) + 1)) == (char *)NULL))
return 0;
/* Get the next available job number */
while (TRUE)
{
jp->pid = pid;
jp->Number = JobNumber++;
if (JobNumber > 32000)
JobNumber = 1;
if (tfind (jp, &JobTree, SearchJob) == (void *)NULL)
break;
}
/* Disable signals */
save_signal = signal (SIGINT, SIG_IGN);
if (tsearch (jp, &JobTree, SearchJob) != (void *)NULL)
{
SetMemoryAreaNumber ((void *)jp, 0);
SetMemoryAreaNumber ((void *)strcpy (jp->Command, command), 0);
PATH_TO_UNIX (jp->Command);
}
/* Restore signals */
signal (SIGINT, save_signal);
PreviousJob = CurrentJob;
return CurrentJob = jp->Number;
}
/*
* Display Jobs
*/
int PrintJobs (bool Mode)
{
DisplayListMode = Mode; /* Set mode */
twalk (JobTree, DisplayJob);
return 0;
}
/*
* Count the number of active jobs
*/
int NumberOfActiveJobs (void)
{
NumberOfJobs = 0;
twalk (JobTree, CountJob);
return NumberOfJobs;
}
/*
* Print Process Tree
*
* Declare OS2 1.x 16-bit version structures
*/
typedef struct process
{
USHORT pid;
USHORT ppid;
USHORT threads;
USHORT children;
USHORT modhandle;
USHORT module;
} V1Process_t;
typedef struct module
{
USHORT modhandle;
USHORT max_dependents;
USHORT *dependents;
UCHAR *modname;
} V1Module_t;
struct ProcessInfo
{
V1Process_t **V1Processes;
V1Module_t **V1Modules;
USHORT M_Processes;
USHORT N_Processes;
USHORT M_Modules;
USHORT N_Modules;
};
/*
* OS2 2.0 - 32 Bit version structures
*/
#define PTR(ptr, ofs) ((void *)((char *)(((ULONG) ps & 0xFFFF0000) | (USHORT) (ptr)) + (ofs)))
/* Process Status structures */
struct V2_ProcessStatus
{
ULONG summary;
ULONG processes;
ULONG semaphores;
ULONG unknown1;
ULONG sharedmemory;
ULONG modules;
ULONG unknown2;
ULONG unknown3;
};
typedef struct process2
{
ULONG type;
ULONG threadlist;
USHORT processid;
USHORT parentid;
ULONG unknown1;
ULONG unknown2;
USHORT sessionid;
USHORT unknown3;
USHORT modulehandle;
USHORT threads;
USHORT sessiontype;
/* lots of other unknown data */
} V2Process_t;
typedef struct thread2
{
ULONG unknown1;
USHORT threadid;
USHORT threadsysid;
ULONG blockid;
USHORT priority;
USHORT unknown2;
ULONG unknown3;
ULONG unknown4;
USHORT status;
USHORT unknown5;
} V2Thread_t;
/*
* OS2 1.x - Parse the kernel process information
*/
static bool near Parse_V1ProcessTable (UCHAR * bBuf, struct ProcessInfo *pi)
{
USHORT sel, offs;
USHORT type, tpid;
USHORT count, kount;
UCHAR buffer[256];
UCHAR *cptr, *ptr;
ptr = bBuf;
sel = SELECTOROF(ptr);
while ((type = *(USHORT *) ptr) != 0xFFFFU )
{
ptr += 2;
offs = *(USHORT *) ptr;
ptr += 2;
switch ( type )
{
case 0: /* Process */
if (pi->N_Processes >= pi->M_Processes)
{
V1Process_t **newp;
newp = (V1Process_t **)GetAllocatedSpace (
(pi->M_Processes + 50) * sizeof (V1Process_t *));
if (newp == (V1Process_t **)NULL)
return TRUE;
memcpy ((void *)newp, (void *)pi->V1Processes,
sizeof (V1Process_t *) * pi->M_Processes);
ReleaseMemoryCell ((void *)pi->V1Processes);
pi->V1Processes = newp;
pi->M_Processes += 50;
}
/* Create the process entry */
pi->V1Processes[pi->N_Processes] =
(V1Process_t *) GetAllocatedSpace (sizeof (V1Process_t));
if (pi->V1Processes[pi->N_Processes] == (V1Process_t *)NULL)
return TRUE;
pi->V1Processes[pi->N_Processes]->pid = *(USHORT *)ptr;
ptr += 2;
pi->V1Processes[pi->N_Processes]->ppid = *(USHORT *) ptr;
ptr += 2;
ptr += 2;
pi->V1Processes[pi->N_Processes]->modhandle = *(USHORT *) ptr;
pi->V1Processes[pi->N_Processes++]->threads = 0;
break;
case 1: /* Thread */
ptr += 2;
tpid = *(USHORT *) ptr;
/* Increment the thread count for the process */
for (count = 0; count < pi->N_Processes; count++)
{
if (pi->V1Processes[count]->pid == tpid)
{
++pi->V1Processes[count]->threads;
break;
}
}
break;
case 2: /* module */
if (pi->N_Modules >= pi->M_Modules)
{
V1Module_t **newm;
newm = (V1Module_t **)GetAllocatedSpace (
(pi->M_Modules + 50) * sizeof (V1Module_t *));
if (newm == (V1Module_t **)NULL)
return TRUE;
memcpy ((void *)newm, (void *)pi->V1Modules,
sizeof (V1Module_t *) * pi->M_Modules);
ReleaseMemoryCell ((void *)pi->V1Modules);
pi->V1Modules = newm;
pi->M_Modules += 50;
}
pi->V1Modules[pi->N_Modules]
= (V1Module_t *)GetAllocatedSpace (sizeof(V1Module_t));
if (pi->V1Modules[pi->N_Modules] == (V1Module_t *)NULL)
return TRUE;
pi->V1Modules[pi->N_Modules]->modhandle = *(USHORT *) ptr;
ptr += 2;
pi->V1Modules[pi->N_Modules]->max_dependents = *(USHORT *) ptr;
ptr += 2;
ptr += 2;
ptr += 2;
if (pi->V1Modules[pi->N_Modules] -> max_dependents)
ptr += (pi->V1Modules[pi->N_Modules] -> max_dependents) * 2;
for (cptr = buffer; *cptr++ = *ptr++;)
continue;
if ((pi->V1Modules[pi->N_Modules]->modname =
StringCopy (buffer)) == null)
return 1;
++pi->N_Modules;
break;
case 3: /* system semaphore */
case 4: /* shared memory */
break;
}
ptr = MAKEP(sel, offs);
}
/* Count modules */
for (count = 0; count < pi->N_Processes; count++)
{
for (kount = 0; kount < pi->N_Modules; kount++)
{
if (pi->V1Processes[count]->modhandle ==
pi->V1Modules[kount]->modhandle)
{
pi->V1Processes[count]->module = kount;
break;
}
}
}
/* Count children */
for (count = 0; count < pi->N_Processes; count++)
{
for (kount = 0; kount < pi->N_Processes; kount++)
{
if (pi->V1Processes[count]->pid == pi->V1Processes[kount]->ppid)
(pi->V1Processes[count]->children)++;
}
}
return FALSE;
}
/*
* Process the process information
*/
static void near PrintV1ProcessTree (pid_t pid, int indent,
struct ProcessInfo *pi)
{
USHORT count;
UCHAR *mName, pName[256];
for (count = 0; count < pi->N_Processes; count++)
{
if ((pi->V1Processes[count]->ppid == (USHORT)pid) ||
((!indent) && (pi->V1Processes[count]->pid == (USHORT)pid)))
{
if (pi->V1Processes[count]->module)
{
mName = pi->V1Modules[pi->V1Processes[count]->module]->modname;
DosGetModName (pi->V1Processes[count]->modhandle,
sizeof(pName), pName);
}
else
{
mName = "unknown"; /* Zombie process, */
pName[0] = 0;
}
printf ("%5d %5d %3d %-8s %*s%s\n", pi->V1Processes[count]->pid,
pi->V1Processes[count]->ppid,
pi->V1Processes[count]->threads, mName, indent, "", pName);
PrintV1ProcessTree (pi->V1Processes[count]->pid, indent + 2, pi);
}
}
}
int SortV1Processes (void *p1, void *p2)
{
return (*(V1Process_t **)p1)->pid - (*(V1Process_t **)p2)->pid;
}
/*
* OS/2 2.x 32-bit version - Display Process Tree
*/
static void near V2_DisplayProcessTree (USHORT pid, USHORT indent,
struct V2_ProcessStatus *ps)
{
V2Process_t *proc;
UCHAR name[256];
USHORT prty;
for (proc = PTR (ps->processes, 0);
proc -> type != 3; /* not sure if there isn't */
/* another termination method */
proc = PTR (proc -> threadlist,
proc -> threads * sizeof (V2Thread_t))
)
{
if ((proc->parentid == pid) ||
((!indent) && (proc->processid == pid)))
{
if (DosGetModName (proc->modulehandle, sizeof (name), name))
strcpy(name, "<unknown>");
if (DosGetPrty (PRTYS_PROCESS, &prty, proc->processid))
prty = 0;
printf ("%5d %5d %3d %04x %*s%s\n", proc->processid,
proc->parentid, proc->threads, prty, indent, "", name);
V2_DisplayProcessTree (proc->processid, indent + 2, ps);
}
}
}
/*
* Print the Process Tree
*/
int PrintProcessTree (pid_t pid)
{
/* Switch on release number */
if (_osmajor < 20)
{
UCHAR *pBuf = GetAllocatedSpace (0x2000);
USHORT count;
struct ProcessInfo pi;
pi.M_Processes = pi.M_Modules = pi.N_Processes = pi.N_Modules = 0;
pi.V1Processes = NULL;
pi.V1Modules = NULL;
if (pBuf == (UCHAR *)NULL)
return 1;
DosQProcStatus (pBuf, 0x2000);
if (Parse_V1ProcessTable (pBuf, &pi))
return 1;
ReleaseMemoryCell ((void *)pBuf);
qsort ((void *)pi.V1Processes, pi.N_Processes, sizeof (V1Process_t *),
SortV1Processes);
puts (" PID PPID TC Name Program");
PrintV1ProcessTree (pid, 0, &pi);
for (count = 0; count < pi.N_Processes; count++)
ReleaseMemoryCell ((void *)pi.V1Processes[count]);
for (count = 0; count < pi.N_Modules; count++)
{
ReleaseMemoryCell ((void *)pi.V1Modules[count] -> modname);
ReleaseMemoryCell ((void *)pi.V1Modules[count]);
}
ReleaseMemoryCell ((void *)pi.V1Processes);
ReleaseMemoryCell ((void *)pi.V1Modules);
}
/*
* OS2 2.0 - grap space, get the information and display it
*/
else
{
struct V2_ProcessStatus *ps;
if ((ps = (struct V2_ProcessStatus *)GetAllocatedSpace (0x8000))
== (struct V2_ProcessStatus *)NULL)
return 1;
DosQProcStatus (ps, 0x8000);
puts (" PID PPID TC PRI Program");
V2_DisplayProcessTree (pid, 0, ps);
ReleaseMemoryCell ((void *)ps);
}
return 0;
}
#endif